#from openopt import NLP, GLP
from scipy import optimize
#from numpy import cos, arange, ones, asarray, abs, zeros, sqrt, asscalar, array, pi
import numpy as np

import JT
import JT.JTconfig as config

import gdata.spreadsheet.text_db
import my_auth
from socket import gethostname
from datetime import datetime
import time

user = gethostname()

from win32api import GetSystemMetrics

class Test():
    def __init__(self):            

#===============================================================================
#    Google Data Upload Setup
#===============================================================================
        cred = my_auth.credentials()
        username = cred.name
        password = cred.pw
        db_name = 'data'
        sheet_name = 'raw'
        self._connectSuccess = False
        
        try:
            client = gdata.spreadsheet.text_db.DatabaseClient()
            client.SetCredentials(username,password)
            time.sleep(.5)
            db = client.GetDatabases(name=db_name)[0]
            self.table = db.GetTables(name=sheet_name)[0]
            self._connectSuccess = True
        except:
            print 'Could not connect to Google'
            
#===============================================================================
#    Setup DRR
#===============================================================================
        drr = JT.DRR()
        
        cal = JT.ExternalCalibration()
        cal.LoadConsolidatedCalibration(config.calFileLat)
        cal.LoadStaFile(config.staFile)
        
        xraycam.SetExternalCalibration(cal)
        
        self.volume = JT.Volume()
        self.volume.SetVolumeFilename(config.inputVolFileName)
        self.volume.SetOriginalTransform(cal._VolumeT)
        self.volume.SetBodyCenter((3.906, 2.17, -7.378))
        #self.volume.UseRayCastMapper()
        drr.AddVolume(self.volume)
        
        drr._renWin.SetOffScreenRendering(0)
        
        # Set Fixed image using path
        self.fixedImage = JT.FixedImage()
        self.fixedImage.SetFileName(config.fixedImageName)

        self.reg=JT.Registration()
        self.reg.SetFixedImage(self.fixedImage.GetImage(0))
        self.reg.SetMovingImageGenerator(drr)
        self.reg.SetRegionOfInterest(config.roi)
        
        #Create a separate window to show fixed image
        self.fixedImageWin = JT.ImageCanvas()
        
        
        self.T = JT.Testing()


    def run_test(self,n_pose=50,level=4,method='gc',debug=True,plot=False,upload_data=True):    
    #===============================================================================
    #    Setup Optimizer
    #===============================================================================
    # Select the desired starting pose, between [0,200)
        pose = self.T.GetStartPose(n_pose)
        print "Starting Pose: ", pose
        
        # Set up images according to level
        #self.fixedImage.ShrinkImage(level)
        #self.volume.ShrinkVolume(level)
        #print "images reduced by a factor of ", level
        
        # Update the fixedImageWin
#        self.fixedImageWin.SetImage(self.fixedImage.GetImage(0))
#        self.fixedImageWin.SetPosition(GetSystemMetrics(0)-
#                                       self.fixedImageWin.GetSize()[0],0)
#        self.fixedImageWin.Render()
        
        # Choose metric and bounds (step size?) for search
        self.reg.SetImageMetric(method)
        #self.reg._useSmoothImages = True
        self.reg._factor = 4
        
        lowerBounds = pose - config.search_range/2
        upperBounds = pose + config.search_range/2
        
        x0 = pose
        f=self.reg.GetValue
        
        start_time = time.time()
        (xmin, Jmin, T, feval, iters, accept, retval) = optimize.anneal(
                                    f, x0, args=(debug,plot), full_output=True, 
                                    T0=config.T0, Tf=config.Tf, lower=lowerBounds, 
                                    upper=upperBounds, m=config.m, n=config.n,
                                    maxiter=config.maxiter, maxeval=config.maxeval, 
                                    maxaccept=config.maxaccept, dwell=config.dwell, 
                                    feps=config.feps, schedule=config.schedule,
                                    boltzmann=config.boltzmann, quench=config.quench, 
                                    learn_rate=config.learn_rate)
        end_time = time.time()
        
        #===============================================================================
        #    Display/Save Results
        #===============================================================================
        #(params, fopt, direc, numiter, func_calls, warnflag, allvecs) = retval
        
        print "Performed %i function evaluations, in %f seconds, best cost function: %f" \
               % (feval,end_time-start_time,Jmin)
        
        print "Optimizer exited with the message:"
        if retval==0:
            print "    Cooled to global optimum"    
        elif retval==1:
            print "    Cooled to final temperature"
        elif retval==2:
            print "    Maximum function evaluations"
        elif retval==3:
            print "    Maximum cooling iterations reached"
        elif retval==4:
            print "    Maximum accepted query locations reached"
            
        print "Starting Pose: ", pose
        print "Final Pose   : ", xmin
        print "Acceptances  : ", accept
        
        # Save registration data to file for analysis of tuning parameters
        log_path = 'C:/Users/bryan/bryan-code/trunk/Results/Reg.log'
        log = open(log_path,'a')
        output = (str(Jmin),str(xmin[0]),str(xmin[1]),str(xmin[2]),str(xmin[3]),
                  str(xmin[4]),str(xmin[5]),str(x0[0]),str(x0[1]),str(x0[2]),
                  str(x0[3]),str(x0[4]),str(x0[5]),
                  str(config.search_range[0]),str(config.search_range[1]),
                  str(config.search_range[2]),str(config.search_range[3]),
                  str(config.search_range[4]),str(config.search_range[5]),
                  str(config.T0),str(config.Tf),str(config.maxiter),
                  str(config.maxeval),str(config.maxaccept),str(config.dwell),
                  str(config.feps),str(retval),config.schedule,
                  str(config.boltzmann),str(feval),method,
                  str(config.quench),str(config.m),str(config.n))
        
        output = '\t'.join(output)
        log.write(output)
        log.write('\n')
        log.close()
        
        if upload_data and self._connectSuccess:
            dt = datetime.fromtimestamp(time.time())
            time_stamp = dt.strftime('%m/%d/%Y_%H:%M:%S')
            output_dict = dict(user = user,
                               timestamp = time_stamp,
                               finalcost = str(Jmin),
                               final0 = str(xmin[0]),
                               final1 = str(xmin[1]),
                               final2 = str(xmin[2]),
                               final3 = str(xmin[3]),
                               final4 = str(xmin[4]),
                               final5 = str(xmin[5]),
                               initial0 = str(x0[0]),
                               initial1 = str(x0[1]),
                               initial2 = str(x0[2]),
                               initial3 = str(x0[3]),
                               initial4 = str(x0[4]),
                               initial5 = str(x0[5]),
                               bounds0 = str(config.search_range[0]),
                               bounds1 = str(config.search_range[1]),   
                               bounds2 = str(config.search_range[2]),
                               bounds3 = str(config.search_range[3]),
                               bounds4 = str(config.search_range[4]),
                               bounds5 = str(config.search_range[5]),
                               t0 = str(config.T0),
                               tf = str(config.Tf),
                               maxiter = str(config.maxiter),
                               maxeval = str(config.maxeval),
                               maxaccept = str(config.maxaccept),
                               dwell = str(config.dwell),
                               feps = str(config.feps),
                               retval = str(retval),
                               schedule = config.schedule,
                               boltzmann = str(config.boltzmann),
                               fevals = str(feval),
                               method = method,
                               quench = str(config.quench),
                               m = str(config.m),
                               n = str(config.n),
                               npose = str(n_pose),
                               runningtime = str(end_time-start_time))
            record = self.table.AddRecord(output_dict)
            print "Data written to google spreadsheet!"
            #print record.content

if __name__ == "__main__":
    T = Test()
    for i in range(10):
        T.run_test(method='bpc',n_pose=50,plot=False)
        # Reset the reg class for the next run
        T.reg.Reset()
        JT.PlotResultsFromFile.run()
    
    #pylab.show()


